/*
 * Copyright (C) 2021 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.byox.drawview.utils;

import ohos.agp.components.Component;
import ohos.app.Context;
import ohos.multimodalinput.event.TouchEvent;

/**
 * ScaleGestureDetector 类
 *
 * @since 2021-08-06
 */
public class ScaleGestureDetector {
    private static final float NUM_ONE = 0.8f;
    private static final float NUM_ZEROONE = 0.1f;
    private static final float NUM_TWO = 2.0f;
    private static final int NUM_EIGHT = 8;
    private static final int INVALID_POINTER_INDEX = -1;
    private float fx;
    private float fy;
    private float sx;
    private float sy;
    private int mPointerIndex1;
    private int mPointerIndex2;
    private float mScale = 1;

    private OnScaleGestureListener mListener;
    private boolean isActive = false;

    /**
     * ScaleGestureDetector 方法
     *
     * @param context 上下文
     * @param listener 监听
     */
    public ScaleGestureDetector(Context context, OnScaleGestureListener listener) {
        mListener = listener;
        mPointerIndex1 = INVALID_POINTER_INDEX;
        mPointerIndex2 = INVALID_POINTER_INDEX;
    }

    /**
     * isActive方法
     *
     * @return isActive对象
     */
    public boolean isActive() {
        return isActive;
    }

    /**
     * setActive方法
     *
     * @param active 对象
     */
    public void setActive(boolean active) {
        isActive = active;
    }

    /**
     * getScale方法
     *
     * @return mScale对象
     */
    public float getScale() {
        return mScale;
    }

    /**
     * onTouchEvent 方法
     *
     * @param component 组件
     * @param event 事件
     * @return boolean方法
     */
    public boolean onTouchEvent(Component component, TouchEvent event) {
        switch (event.getAction()) {
            case TouchEvent.PRIMARY_POINT_DOWN:
                sx = event.getPointerScreenPosition(0).getX();
                sy = event.getPointerScreenPosition(0).getY();
                mPointerIndex1 = event.getPointerId(0);
                break;
            case TouchEvent.OTHER_POINT_DOWN:
                fx = event.getPointerScreenPosition(0).getX();
                fy = event.getPointerScreenPosition(0).getY();
                mPointerIndex2 = event.getPointerId(event.getIndex());
                break;
            case TouchEvent.POINT_MOVE:
                if (INVALID_POINTER_INDEX != mPointerIndex1
                        && mPointerIndex2 != INVALID_POINTER_INDEX
                        && mPointerIndex2 < event.getPointerCount()) {
                    isActive = true;
                    final float nfX;
                    final float nfY;
                    final float nsX;
                    final float nsY;
                    nsX = event.getPointerScreenPosition(mPointerIndex1).getX();
                    nsY = event.getPointerScreenPosition(mPointerIndex1).getY();
                    nfX = event.getPointerScreenPosition(mPointerIndex2).getX();
                    nfY = event.getPointerScreenPosition(mPointerIndex2).getY();
                    calculateScaleBetweenLines(nfX, nfY, nsX, nsY);
                    if (mListener != null) {
                        mListener.onScale(this);
                    }
                    fx = nfX;
                    fy = nfY;
                    sx = nsX;
                    sy = nsY;
                }
                break;
            case TouchEvent.PRIMARY_POINT_UP:
                mPointerIndex1 = INVALID_POINTER_INDEX;
                break;
            case TouchEvent.OTHER_POINT_UP:
                mPointerIndex2 = INVALID_POINTER_INDEX;
                break;
            default:
                break;
        }
        return true;
    }

    private void calculateScaleBetweenLines(float sx1, float sy1, float sx2, float sy2) {
        float absX = Math.abs(fx - sx);
        float absY = Math.abs(fy - sy);

        float absXt = Math.abs(sx1 - sx2);
        float absYt = Math.abs(sy1 - sy2);

        if (absX > absXt || absY > absYt) {
            if (mScale > NUM_ONE) {
                mScale = mScale - NUM_ZEROONE;
            }
        }
        if (absX < absXt || absY < absYt) {
            mScale = mScale + NUM_ZEROONE;
            if (mScale > NUM_EIGHT) {
                mScale = NUM_EIGHT;
            }
        }
    }

    /**
     * getFocusX方法
     *
     * @return (fx + sx) / NUM_TWO 值
     */
    public float getFocusX() {
        return (fx + sx) / NUM_TWO;
    }

    /**
     * getFocusY方法
     *
     * @return (fy + sy) / NUM_TWO值
     */
    public float getFocusY() {
        return (fy + sy) / NUM_TWO;
    }

    /**
     * OnScaleGestureListener 接口
     *
     * @since 2021-08-06
     */
    public interface OnScaleGestureListener {
        /**
         * onScale接口
         *
         * @param scaleDetector
         * @return boolean类型
         */
        boolean onScale(ScaleGestureDetector scaleDetector);
    }
}
